package com.demo.service;

import com.alibaba.fastjson.JSON;
import com.demo.annotation.CacheExpire;
import com.demo.annotation.ShardingStrategy;
import com.demo.dao.mapper.UserMapper;
import com.demo.model.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cursor.Cursor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author K
 */
@Slf4j
@Service
public class UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private DbShardingStrategyService dbShardingStrategyService;

    public void saveUser() {
        dbShardingStrategyService.insertAfterPublisher(System.currentTimeMillis());
        log.info("saveUser");
    }

    @Cacheable(cacheNames = "user:getUser:", key = "#userId")
    @CacheExpire(2060)
    public List<User> getUser(Long userId) {
        return dbShardingStrategyService.selectByUserId(userId);
    }

    /**
     * 如果用key找对象属性的值，CacheExpire设置的过期时间失效。因为在容器初始化设置“user:getUser: + 值”的过期时间
     * 但是使用key=#user.userId生成的缓存key是"user:getUser:userId + 值“，所以过去时间无效
     * @param user 用户查询参数
     * @return 用户集合
     */
    @Cacheable(cacheNames = "user:getUser:", key = "#user.userId")
    @CacheExpire(60)
    public List<User> getUser(User user) {
        return dbShardingStrategyService.selectByUserId(user.getUserId());
    }

    /**
     *
     * @param userId 用户id
     * @return 用户集合
     */
    @Cacheable(cacheNames = "user:getUser:userId:", key = "#userId")
    @CacheExpire(2000)
    public List<User> getUserByUserId(Long userId) {
        return dbShardingStrategyService.selectByUserId(userId);
    }

    /**
     * 返回null不缓存
     * @param userId 用户id
     * @return null对象
     */
    @Cacheable(cacheNames = "user:returnNull:", key = "#userId", unless = "#result == null")
    public List<User> returnNull(Long userId) {
        log.info("用户id：{}", userId);
        return null;
    }

    /**
     * 删除缓存
     * @param userId 用户id
     */
    @CacheEvict(cacheNames = "user:getUser:", key = "#userId")
    public void deleteCache(Long userId) {}

    /**
     * 通过mybatis Cursor获取大批量数据
     * sharding-jdbc 不支持 jdbc4.1新功能
     * @param dbIndex 指定数据索引
     * @return 用户集合
     * @throws IOException 游标异常信息
     */
    @Transactional(rollbackFor = Exception.class)
    @ShardingStrategy(dbIndex = "#dbIndex")
    public List<User> queryAll(long dbIndex) throws IOException {
        List<User> list = new ArrayList<>();
        try(Cursor<User> users = userMapper.queryAll()) {
            users.forEach(user -> list.add(user));
        }
        log.info("游标用户集合：{}", JSON.toJSONString(list));
        return list;
    }
}
